#include "groupdemo.h"
#include <iostream>
#include <emchatmanager_interface.h>
#include <emgroupmanager_interface.h>
#include <emcallback.h>
#include <emlogininfo.h>

using namespace std;
using namespace easemob;

GroupDemo::GroupDemo():BaseConfig() {

    cout << "========  GroupDemo  ========" << endl;
}

class GroupListener : public EMGroupManagerListener {
public:
    GroupListener(){}
    void onReceiveInviteFromGroup(const std::string groupId, const std::string& inviter, const std::string& inviteMessage) {}
    void onReceiveInviteAcceptionFromGroup(const EMGroupPtr group, const std::string& invitee) {}
    void onReceiveInviteDeclineFromGroup(const EMGroupPtr group, const std::string& invitee, const std::string &reason) {}
    void onAutoAcceptInvitationFromGroup(const EMGroupPtr group, const std::string& inviter, const std::string& inviteMessage) {}
    void onLeaveGroup(const EMGroupPtr group, EMMuc::EMMucLeaveReason reason) {}
    void onReceiveJoinGroupApplication(const EMGroupPtr group, const std::string& from, const std::string& message) {}
    void onReceiveAcceptionFromGroup(const EMGroupPtr group) {}
    void onReceiveRejectionFromGroup(const std::string &groupId, const std::string &reason) {}
    void onUpdateMyGroupList(const std::vector<EMGroupPtr> &list) {};
    void onAddMutesFromGroup(const EMGroupPtr group, const std::vector<std::string> &mutes, int64_t muteExpire) {};
    void onRemoveMutesFromGroup(const EMGroupPtr group, const std::vector<std::string> &mutes) {};
    void onAddWhiteListMembersFromGroup(const easemob::EMGroupPtr Group, const std::vector<std::string> &members) {};
    void onRemoveWhiteListMembersFromGroup(const easemob::EMGroupPtr Group, const std::vector<std::string> &members) {};
    void onAllMemberMuteChangedFromGroup(const easemob::EMGroupPtr Group, bool isAllMuted) {};
    void onAddAdminFromGroup(const EMGroupPtr group, const std::string& admin) {};
    void onRemoveAdminFromGroup(const EMGroupPtr group, const std::string& admin) {};
    void onAssignOwnerFromGroup(const EMGroupPtr group, const std::string& newOwner, const std::string& oldOwner) {};
    void onMemberJoinedGroup(const EMGroupPtr group, const std::string& member) {};
    void onMemberLeftGroup(const EMGroupPtr group, const std::string& member) {};
    void onUpdateAnnouncementFromGroup(const EMGroupPtr group, const std::string& announcement) {};
    void onUploadSharedFileFromGroup(const EMGroupPtr group, const EMMucSharedFilePtr sharedFile) {};
    void onDeleteSharedFileFromGroup(const EMGroupPtr group, const std::string& fileId) {};
};



void GroupDemo::testGroup() {

    easemob::EMErrorPtr retPtr = mClient->login(TestAccounts[0], "123456");
    if (retPtr->mErrorCode != EMError::EM_NO_ERROR)
    {
        std::cerr << "login failed!" << retPtr->mErrorCode << std::endl;
        return;
    }
    std::cout << "login success!" << std::endl;


    // createGroup
    EMError error;
    int maxUserCount = 200;
    bool inviteNeedConfirm = false;
    auto group = mClient->getGroupManager().createGroup("testGroupName", "description", "WelcomeMessage", EMMucSetting(EMMucSetting::EMMucStyle::DEFAUT, maxUserCount, inviteNeedConfirm), {TestAccounts[2], TestAccounts[3]}, error);

    if(error.mErrorCode != EMError::EM_NO_ERROR) {
        std::cerr << "create Group failed, cause by: " << error.mDescription << std::endl;
        return;
    }

    std::cout << group->groupSubject() << " created by " << group->groupOwner() << " success !" << std::endl;

    auto group2 = mClient->getGroupManager().createGroup("testPublicGroup", "desc", "welcome", EMMucSetting(EMMucSetting::EMMucStyle::PUBLIC_JOIN_OPEN, maxUserCount, inviteNeedConfirm), {}, error);

    if(error.mErrorCode != EMError::EM_NO_ERROR) {
        std::cerr << "create Group failed, cause by: " << error.mDescription << std::endl;
        return;
    }

    std::cout << group->groupSubject() << " created by " << group->groupOwner() << " success !" << std::endl;

    auto groupListener = std::unique_ptr<GroupListener>(new GroupListener());

    mClient->getGroupManager().addListener(groupListener.get());


    mClient->getGroupManager().addGroupMembers(group->groupId(), {TestAccounts[1]}, "welcome", error);

    if(error.mErrorCode != EMError::EM_NO_ERROR) {
        std::cerr << "invite user to Group failed, cause by: " << error.mDescription << std::endl;
        return;
    }

    mClient->getGroupManager().addGroupAdmin(group->groupId(), TestAccounts[1], error);

    if(error.mErrorCode != EMError::EM_NO_ERROR) {
        std::cerr << "addGroupAdmin failed, cause by: " << error.mDescription << std::endl;
        return;
    }

    mClient->getGroupManager().removeGroupAdmin(group->groupId(), TestAccounts[1], error);
    if(error.mErrorCode != EMError::EM_NO_ERROR) {
        std::cerr << "removeGroupAdmin failed, cause by: " << error.mDescription << std::endl;
        return;
    }

    mClient->getGroupManager().blockGroupMembers(group->groupId(),{TestAccounts[1]}, error);

    if(error.mErrorCode != EMError::EM_NO_ERROR) {
        std::cerr << "blockGroupMembers failed, cause by: " << error.mDescription << std::endl;
        return;
    }

    auto memBlackList = mClient->getGroupManager().fetchGroupBans(group->groupId(), 1, 200, error);

    if(error.mErrorCode != EMError::EM_NO_ERROR || memBlackList.empty()) {
        std::cerr << "fetchGroupBans failed, cause by: " << error.mDescription << std::endl;
        return;
    } else if(memBlackList.empty()) {
        std::cerr << "fetchGroupBans size is zero" << std::endl;
        return;
    }

    if(error.mErrorCode != EMError::EM_NO_ERROR) {
        std::cerr << "blockGroupMembers failed, cause by: " << error.mDescription << std::endl;
        return;
    }


    mClient->getGroupManager().unblockGroupMembers(group->groupId(),{TestAccounts[1]}, error);
    if(error.mErrorCode != EMError::EM_NO_ERROR) {
        std::cerr << "unblockGroupMembers failed, cause by: " << error.mDescription << std::endl;
        return;
    }

    mClient->getGroupManager().addGroupMembers(group->groupId(), {TestAccounts[1]}, "welcome", error);

    if(error.mErrorCode != EMError::EM_NO_ERROR) {
        std::cerr << "add user to Group failed, cause by: " << error.mDescription << std::endl;
        return;
    }

    mClient->getGroupManager().muteGroupMembers(group->groupId(), {TestAccounts[2]}, 60 * 60 * 1000, error);

    if(error.mErrorCode != EMError::EM_NO_ERROR) {
        std::cerr << "muteGroupMembers Group failed, cause by: " << error.mDescription << std::endl;
        return;
    }

    auto muteList = mClient->getGroupManager().fetchGroupMutes(group->groupId(), 1, 200, error);
    if(error.mErrorCode != EMError::EM_NO_ERROR) {
        std::cerr << "fetchGroupMutes Group failed, cause by: " << error.mDescription << std::endl;
        return;
    } else if(muteList.empty()) {
        std::cerr << "fetchGroupMutes Group is  empty" << std::endl;
        return;
    }

    mClient->getGroupManager().unmuteGroupMembers(group->groupId(), {TestAccounts[2]}, error);

    if(error.mErrorCode != EMError::EM_NO_ERROR) {
        std::cerr << "unmuteGroupMembers Group failed, cause by: " << error.mDescription << std::endl;
        return;
    }

    mClient->getGroupManager().muteAllGroupMembers(group->groupId(), error);
    if(error.mErrorCode != EMError::EM_NO_ERROR) {
        std::cerr << "muteAllGroupMembers Group failed, cause by: " << error.mDescription << std::endl;
        return;
    }

    mClient->getGroupManager().unmuteAllGroupMembers(group->groupId(), error);
    if(error.mErrorCode != EMError::EM_NO_ERROR) {
        std::cerr << "unmuteAllGroupMembers Group failed, cause by: " << error.mDescription << std::endl;
        return;
    }

    mClient->getGroupManager().addWhiteListMembers(group->groupId(), {TestAccounts[3]}, error);
    if(error.mErrorCode != EMError::EM_NO_ERROR) {
        std::cerr << "addWhiteListMembers Group failed, cause by: " << error.mDescription << std::endl;
        return;
    }

    auto muteWhiteMemList = mClient->getGroupManager().fetchGroupWhiteList(group->groupId(), error);
    if(error.mErrorCode != EMError::EM_NO_ERROR) {
        std::cerr << "fetchGroupWhiteList failed, cause by: " << error.mDescription << std::endl;
        return;
    } else if(muteWhiteMemList.empty()) {
        std::cerr << "fetchGroupWhiteList is empty" << std::endl;
        return;
    }
//    mClient->getGroupManager().fetchIsMemberInWhiteList(group->groupId(), error);

    mClient->getGroupManager().removeWhiteListMembers(group->groupId(), {TestAccounts[3]}, error);
    if(error.mErrorCode != EMError::EM_NO_ERROR) {
        std::cerr << "removeWhiteListMembers Group failed, cause by: " << error.mDescription << std::endl;
        return;
    }

    auto newGroupPtr = mClient->getGroupManager().changeGroupSubject(group->groupId(), "新的群名称", error);
    if(error.mErrorCode != EMError::EM_NO_ERROR) {
        std::cerr << "changeGroupSubject failed, cause by: " << error.mDescription << std::endl;
        return;
    } else if(newGroupPtr->groupSubject() != "新的群名称") {
        std::cerr << "new groupSubject change failed " << std::endl;
        return;
    }

    mClient->getGroupManager().changeGroupDescription(group->groupId(), "新的群描述", error);
    if(error.mErrorCode != EMError::EM_NO_ERROR) {
        std::cerr << "changeGroupDescription failed, cause by: " << error.mDescription << std::endl;
        return;
    }

    mClient->getGroupManager().updateGroupAnnouncement(group->groupId(), "新的群公告", error);
    if(error.mErrorCode != EMError::EM_NO_ERROR) {
        std::cerr << "updateGroupAnnouncement failed, cause by: " << error.mDescription << std::endl;
        return;
    }

    std::string newGroupAnnouncement = mClient->getGroupManager().fetchGroupAnnouncement(group->groupId(), error);
    if(error.mErrorCode != EMError::EM_NO_ERROR) {
        std::cerr << "fetchGroupAnnouncement failed, cause by: " << error.mDescription << std::endl;
        return;
    } else if(newGroupAnnouncement != "新的群公告") {
        std::cerr << "newGroupAnnouncement change failed " << std::endl;
        return;
    }






    mClient->getGroupManager().removeGroupMembers(group->groupId(), {"ceshib"}, error);

    if(error.mErrorCode != EMError::EM_NO_ERROR) {
        std::cout << "remove user to Group failed, cause by: " << error.mDescription << std::endl;
        return;
    }


    mClient->getGroupManager().addGroupMembers(group2->groupId(), {"ceshib"}, "welcome", error);

    if(error.mErrorCode != EMError::EM_NO_ERROR) {
        std::cout << "invite user to Group2 failed, cause by: " << error.mDescription << std::endl;
        return;
    }

    mClient->getGroupManager().transferGroupOwner(group2->groupId(), "ceshib", error);

    if(error.mErrorCode != EMError::EM_NO_ERROR) {
        std::cout << "transferGroupOwner failed, cause by: " << error.mDescription << std::endl;
        return;
    }

    std::string cursor{""};
    int pageSize = 20;
    EMCursorResult result = mClient->getGroupManager().fetchPublicGroupsWithCursor(cursor, pageSize, error);

    if(error.mErrorCode != EMError::EM_NO_ERROR) {
        std::cout << "get public group failed, cause by: " << error.mDescription << std::endl;
        return;
    }

    for(const auto& groupInfo : result.result()) {
        std::cout << std::dynamic_pointer_cast<EMGroup>(groupInfo)->groupSubject() << std::endl;
    }

//    auto groupPtr = mClient->getGroupManager().groupWithId(group->groupId());

    auto groupPtrFromServer = mClient->getGroupManager().fetchGroupSpecification(group->groupId(), error);

    if(error.mErrorCode != EMError::EM_NO_ERROR) {
        std::cout << "groupPtrFromServer failed, cause by: " << error.mDescription << std::endl;
        return;
    }

    std::cout << "groupPtrFromServer isMessageBlocked: " << groupPtrFromServer->isMessageBlocked() << std::endl;

    auto cursorResult = mClient->getGroupManager().fetchGroupMembers(group->groupId(), cursor, pageSize, error);

    if(error.mErrorCode != EMError::EM_NO_ERROR) {
        std::cout << "fetchGroupMembers failed, cause by: " << error.mDescription << std::endl;
        return;
    }

    auto joinedGroups = mClient->getGroupManager().fetchAllMyGroups(error);

    if(error.mErrorCode != EMError::EM_NO_ERROR) {
        std::cout << "joinedGroups failed, cause by: " << error.mDescription << std::endl;
        return;
    }

    mClient->getGroupManager().allMyGroups(error);

    mClient->getGroupManager().blockGroupMessage(group->groupId(), error);

    if(error.mErrorCode != EMError::EM_NO_ERROR) {
        std::cout << "blockGroupMessage failed, cause by: " << error.mDescription << std::endl;
        return;
    }

    std::cout << "blockGroupMessage success, with groupId: " << group->groupId() << std::endl;
    mClient->getGroupManager().unblockGroupMessage(group->groupId(), error);
    std::cout << "unblockGroupMessage success, with groupId: " << group->groupId() << std::endl;

    mClient->getGroupManager().changeGroupExtension(group->groupId(), "newExtension", error);
    if(error.mErrorCode != EMError::EM_NO_ERROR) {
        std::cout << "changeGroupExtension failed, cause by: " << error.mDescription << std::endl;
        return;
    }

    mClient->getGroupManager().destroyGroup(group->groupId(), error);

    if(error.mErrorCode != EMError::EM_NO_ERROR) {
        std::cout << "destroyGroup failed, cause by: " << error.mDescription << std::endl;
        return;
    }
    std::cout << "destroyGroup success with groupId: " << group->groupId() << std::endl;
//
    mClient->getGroupManager().leaveGroup(group2->groupId(), error);
    if(error.mErrorCode != EMError::EM_NO_ERROR) {
        std::cout << "leaveGroup failed, cause by: " << error.mDescription << std::endl;
        return;
    }
    std::cout << "leaveGroup success with groupId: " << group2->groupId() << std::endl;



    mClient->getGroupManager().removeListener(groupListener.get());

    mClient->logout();

}